#include "myStdio.h"

FILE_ *fopen_(const char *path_name,const char *mode)
{
    int flags = 0;
    int defaultMode = 0666; 
    // 读的方式打开
    if(strcmp(mode, "r") == 0)
    {
        flags |= O_RDONLY;// flag = flag|O_RDONLY 
    }
    // 写的方式打开
    else if (strcmp(mode, "w") == 0)
    {
        flags |= (O_WRONLY | O_CREAT | O_TRUNC);
    }
    // 以追加的方式打开
    else if (strcmp(mode,"a") == 0)
    {
        flags |= (O_WRONLY | O_CREAT | O_APPEND);
    }
    else
    {
        // 后面还可以添加其他打开方式
    }
    // 调用系统接口打卡文件
    int fd = 0;
    if(flags & O_RDONLY) fd = open(path_name, flags);
    else fd = open(path_name, flags, defaultMode);
    
    // 判断文件打开状态
    if(fd < 0)
    {
        // 打开文件失败
        const char* err = strerror(errno); // 获取到错误信息
        write(2,err, strlen(err)); // 打印到显示器上面 2是标准输出 write是写入
        return NULL; // 这就是为什么打开文件失败会返回NULL
    }
    FILE_ *fp = (FILE_*)malloc(sizeof(FILE_));
    assert(fp);

    fp->flags = SYNC_NOW;// 默认设置为行刷新
    fp->fileno = fd;
    fp->cap = SIZE;
    fp->size = 0;
    memset(fp->buffer, 0, SIZE);
    
    return fp; // 这就是为什么我们打开一个文件，就会返回一个FILE*指针
}

void fwrite_(const void *ptr, int num, FILE_ *fp)
{
    // 1. 把数据写入到缓冲区中
    memcpy(fp->buffer + fp->size, ptr, num); // 这里不考虑缓冲区溢出的问题
    fp->size += num;
    // 2. 判断是否刷新
    if(fp->flags & SYNC_NOW)
    {
        write(fp->fileno, fp->buffer, fp->size);
        fp->size = 0; // 清空缓冲区
    }
    else if (fp->flags & SYNC_FULL)
    {
        if(fp->size == fp->cap) 
        {
            write(fp->fileno, fp->buffer, fp->size);
            fp->size = 0;
        }
}
    else if (fp->flags & SYNC_LINE)
    {
        if(fp->buffer[fp->size-1] == '\n')
        {
            write(fp->fileno, fp->buffer, fp->size);
            fp->size = 0;
        }
    }
    else
    {

    }    
}

void fflush_(FILE_ *fp)
{
    write(fp->fileno, fp->buffer, fp->size);
}

void fclose_(FILE_* fp)
{
    fflush_(fp);
    close(fp->fileno);
}




